package org.third.integration.ldap;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;

public class LdapSslSocketFactory extends javax.net.SocketFactory {
    private javax.net.ssl.SSLSocketFactory sslSocketFactory;

    public LdapSslSocketFactory() {
        try {
            javax.net.ssl.SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            java.security.KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(LdapSslSocketDelegate.class.getResourceAsStream("idmTrustStore.jks"), "changeit".toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());// SunX509
            tmf.init(trustStore);
            javax.net.ssl.TrustManager[] tms = new TrustManager[1];
            for (TrustManager tm : tmf.getTrustManagers()) {
                if (tm instanceof X509TrustManager) {
                    tms[0] = (X509TrustManager) tm;
                    break;
                }
            }

            sslContext.init(null, tms, new SecureRandom());
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (KeyStoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CertificateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public Socket createSocket() throws IOException {
        return new LdapSslSocketDelegate((SSLSocket)sslSocketFactory.createSocket());
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return new LdapSslSocketDelegate((SSLSocket)sslSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return new LdapSslSocketDelegate((SSLSocket)sslSocketFactory.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return new LdapSslSocketDelegate((SSLSocket)sslSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress host, int port, InetAddress localHost, int localPort) throws IOException {
        return new LdapSslSocketDelegate((SSLSocket)sslSocketFactory.createSocket(host, port, localHost, localPort));
    }

    public javax.net.ssl.SSLSocketFactory getSslSocketFactory() {
        return this.sslSocketFactory;
    }
    /* */
    public static SocketFactory getDefault() {
        return new LdapSslSocketFactory();
    }

}